package org.biojava.services.das.servlets;

import java.io.IOException;
import java.util.Map;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.biojava.services.das.dao.RegistryUser;
import org.biojava.services.das.registry.RegistryConfiguration;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import dasregistry.security.Authenticate;

/**
 * Servlet implementation class Validate
 */
public class ForgottenPassServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	Authenticate authenticate;
	private String emailReturnUrl = "";

	private String emailHost = "";
	private String registryEmail;

	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		ServletContext context = getServletContext();
		emailReturnUrl = context.getInitParameter("returnUrl");//where to return to with  the token 
		//for proof of correct email address
		

		
		//these have already been set using the registry config/spring so we should use these
		RegistryConfiguration rconfig = new RegistryConfiguration();
		// rconfig is set by the outside via Spring
		Map configuration = rconfig.getConfiguration();
		emailHost = (String) configuration.get("sendmailhost");
		registryEmail = (String) configuration.get("serveradmin");
	}

	public ForgottenPassServlet() {
		super();
		BeanFactory ctx = (new ClassPathXmlApplicationContext("SpringDAO.xml"));
		authenticate = (Authenticate) ctx.getBean("authenticate");
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		processNewPassRequest(request, response);

	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		processNewPassRequest(request, response);
		// PrintWriter writer = response.getWriter();
		// writer.println("got authentication request");

	}

	private void processNewPassRequest(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		
		
		String claimedEmail = request.getParameter("claimed_email");
		String registerMe=request.getParameter("registerMe");
		String displayName=request.getParameter("displayName");
		String alertMe=request.getParameter("watchdog");
		System.out.println("claimedDmail=" + claimedEmail);
		HttpSession session = request.getSession();
		String sessionId = session.getId();

		
			//first time getting info for this user
			//check the email doesn't exist in database already
			//Store this user in the session
			//create an a token the same as if theyve forgotten their pass
			//send them an email with token with session id
			
			
		
		// default go back to login
		RequestDispatcher loginDispatcher = request
				.getRequestDispatcher("login.jsp");
		String returnedEmailToken = request.getParameter("emailToken");
		if (returnedEmailToken != null) {
			//link has been clicked in an email check it's the right one for this session
			
			System.out.println("returned email token=" + returnedEmailToken);
			if (session.getAttribute("emailTokenSessionStore").equals(
					returnedEmailToken)) {
				System.out.println("tokens match with session token");

				session.setAttribute("email",
						session.getAttribute("claimed_email"));
				//allow the user with this session to update the password for this claimed email and we have logged them in by setting the email in the session
				RequestDispatcher successDispatcher = request
						.getRequestDispatcher("updatePass.jsp");//on the live and sandbox these should be https requests
				successDispatcher.forward(request, response);
				return;
			}
		}
		//we need an email if registering for the first time or updating a password
		if (claimedEmail == null || claimedEmail.equals("")) {
			session.setAttribute("message",
					"you need to enter an email for us to send you login information");
			session.removeAttribute("email");
			loginDispatcher.forward(request, response);
			return;
		}
		// test user exists
		if (authenticate.userExists(claimedEmail) || registerMe!=null) {
			String emailToken = sessionId + Math.random();
			System.out.println("emailToken=" + emailToken);
			session.setAttribute("emailTokenSessionStore", emailToken);
			session.setAttribute("claimed_email", claimedEmail);
			// if exists send a link to the email address specified
			// Set the host smtp address
			Properties props = new Properties();
			// String sendmailhost = (String) configuration.get("sendmailhost");
			props.put("mail.smtp.host", emailHost);

			// create some properties and get the default Session
			Session mailSession = Session.getDefaultInstance(props, null);
			// System.out.println(session.);
			mailSession.setDebug(false);

			// create a message
			Message msg = new MimeMessage(mailSession);

			// set the from and to address
			try {
				InternetAddress addressFrom = new InternetAddress(registryEmail);
				msg.setFrom(addressFrom);

				InternetAddress[] addressTo = new InternetAddress[1];

				addressTo[0] = new InternetAddress(claimedEmail);

				msg.setRecipients(Message.RecipientType.TO, addressTo);

				// Optional : You can also set your custom headers in the Email
				// if you
				// Want
				// msg.addHeader("MyHeaderName", "myHeaderValue");
				String messageSubject="";
				String messageBody="";
				if(registerMe!=null){
					messageSubject="Request to Register for the DAS Registry?";
					messageBody="We have recieved a request to register you as a user of the DAS Registry. If you have not made this request please contact dasregistry@sanger.ac.uk. If you have made this request please click on the following link set your password ";
					RegistryUser possibleNewUser=new RegistryUser();
					possibleNewUser.setEmail(claimedEmail);
					possibleNewUser.setOpenID(displayName);
					if(alertMe!=null && alertMe.equals("1")){
					possibleNewUser.setAlertMe(true);
					}
					session.setAttribute("possibleNewUser", possibleNewUser);
					
				}else{
				// Setting the Subject and Content Type
				messageSubject="Request to re-set your password for the dasregistry?";
				messageBody="We have recieved a request to reset your password for the DAS Registry. If you have not made this request please contact dasregistry@sanger.ac.uk. If you have made this request please click on the following link to reset your password: ";
				}
				msg.setSubject(messageSubject);
				String link = emailReturnUrl + "whereismypass?emailToken="
						+ emailToken;
				msg.setContent(
						messageBody
								+ link, "text/html");
				Transport.send(msg);
			} catch (AddressException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (MessagingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

//			RequestDispatcher waitForEmailDispatcher = request
//					.getRequestDispatcher("waitForEmail.jsp");
//			waitForEmailDispatcher.forward(request, response);
			response.sendRedirect(emailReturnUrl+"waitForEmail.jsp");//redirect here so we get normal http not https after the user has gone through authentication, also page refreshes will not do a post again!

		} else {
			session.setAttribute("message", "user with email " + claimedEmail
					+ " does not exist would you like to register?");
			loginDispatcher.forward(request, response);
			return;
		}

	}

}
